package com.lc.luzhengtang.view.goodsdetail;

import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.Scroller;

import com.zcx.helper.scale.ScaleScreenHelperFactory;

/**
 * Created by congl on 2017/7/6.
 */

public class GoodsDetailParent2 extends ViewGroup implements NoticeBottomScrollView.OnScrollToBottomListener, NoticeTopWebView.OnScrollToTopListener {

    private static final String TAG = "GoodsDetailParent2";

    //当前显示的是ScrollView部分
    private static final int STATE_CONTENT = 1;
    //当前显示的是WebView部分
    private static final int STATE_WEB = 2;
    //当前处于滑动状态
    private static final int STATE_SCROLL = -1;

    //动画执行的时间
    private static final int DURATION = 500;

    //滚动所用的Scroller
    private Scroller scroller;

    //商品详情ScrollView部分
    private NoticeBottomScrollView top;
    //商品详情WebView部分
    private NoticeTopWebView bottom;

    //ScrollView部分是否滑动到底部
    private boolean isTopToBottom = false;
    //WebView部分是否滑动到顶部
    private boolean isBottomToTop = false;

    //当前是否可滑动
    private boolean isCanScroll;
    //是否在拖拽
    private boolean isUnableToDrag;
    //当前手指滑动方向
    private boolean isScrollToTop;

    //当前的状态
    private int state = STATE_CONTENT;

    //判定为拖动的最小移动像素数
    private int touchSlop;

    //上次手指所处的y坐标
    private float lastMotionY;
    //手指刚刚落下时的y坐标
    private float initialMotionY;
    //上次手指所处的x坐标
    private float lastMotionX;
    //手指刚刚落下时的x坐标
    private float initialMotionX;

    //是否滑动到上下边缘
    private boolean isAbsolute = false;

    private int scrollHeight = -1;
    private int screenHeight;

    private boolean isLoadSuccess = false;

    public GoodsDetailParent2(Context context) {
        super(context);
        init(context);
    }

    public GoodsDetailParent2(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public GoodsDetailParent2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {

        WindowManager wm = (WindowManager) getContext()
                .getSystemService(Context.WINDOW_SERVICE);

        screenHeight = wm.getDefaultDisplay().getHeight();

        scroller = new Scroller(context, sInterpolator);
        ViewConfiguration configuration = ViewConfiguration.get(context);
        // 获取TouchSlop值
        touchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);

        removeAllViews();

        top = new NoticeBottomScrollView(context);
        top.setOnScrollToBottomListener(this);
        addView(top);
        bottom = new NoticeTopWebView(context);
        bottom.setOnScrollToTopListener(this);
        bottom.setEnabled(false);

        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            if (getChildAt(i) instanceof NoticeTopWebView) {
                ((NoticeTopWebView) getChildAt(i)).setEnabled(true);
            }
        }
//        bottom.setOnTouchListener(new OnTouchListener() {
//            @Override
//            public boolean onTouch(View v, MotionEvent event) {
//                return state == STATE_CONTENT;
//            }
//        });
        addView(bottom);

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();

        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            Log.d(TAG, "--> onInterceptTouchEvent:resetTouch()");
            resetTouch();
            return false;
        }

        if (action != MotionEvent.ACTION_DOWN) {
            if (isCanScroll) {
                Log.d(TAG, "--> isCanScroll");
                return true;
            }

            if (isUnableToDrag) {
                Log.d(TAG, "--> isUnableToDrag");
                return false;
            }

        }

        switch (action) {
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "--> ACTION_MOVE");
                final float x = ev.getX();
                final float dx = x - lastMotionX;
                final float xDiff = Math.abs(x - initialMotionX);
                final float y = ev.getY();
                final float dy = y - lastMotionY;
                final float yDiff = Math.abs(dy);

                if (dy != 0 && canScroll(this, false, ((int) dy), ((int) x), ((int) y))) {
                    lastMotionY = y;
                    lastMotionX = x;
                    isUnableToDrag = true;
                    return false;
                }

                Log.d(TAG, "--> yDiff = " + yDiff + ",touchSlop = " + touchSlop + ",xDiff = " + xDiff);

                if (yDiff > touchSlop / 2 && yDiff * 0.5f > xDiff) {
                    Log.d(TAG, "--> yDiff > touchSlop && yDiff * 0.5f > xDiff");
                    isCanScroll = true;
                    lastMotionY = dy > 0 ? initialMotionY + touchSlop / 2 : initialMotionY - touchSlop / 2;
                    requestParentDisallowInterceptTouchEvent(true);
                    lastMotionX = x;
                } else if (xDiff > touchSlop) {
                    isUnableToDrag = true;
                }

                if (isCanScroll) {
                    Log.d(TAG, "--> isCanScroll");
                    performDrag(y);
                }

                break;
            case MotionEvent.ACTION_DOWN:
                lastMotionX = initialMotionX = ev.getX();
                lastMotionY = initialMotionY = ev.getY();
                isUnableToDrag = false;
                isCanScroll = false;
                break;
        }
        return isCanScroll;
    }

    public void setLoadState(boolean isLoadSuccess) {
        this.isLoadSuccess = isLoadSuccess;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(TAG, "--> onTouchEvent");
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                scroller.abortAnimation();
                lastMotionX = initialMotionX = event.getX();
                lastMotionY = initialMotionY = event.getY();

                break;
            case MotionEvent.ACTION_MOVE:

                if (!isCanScroll) {
                    final float x = event.getX();
                    final float xDiff = Math.abs(x - lastMotionX);
                    final float y = event.getY();
                    final float yDiff = Math.abs(y - lastMotionY);

                    if (yDiff > touchSlop / 2 && yDiff > xDiff) {
                        isCanScroll = true;
                        requestParentDisallowInterceptTouchEvent(true);
                        lastMotionX = x;
                        lastMotionY = y - initialMotionY > 0 ? initialMotionY + touchSlop / 2 :
                                initialMotionY - touchSlop / 2;
                        ViewParent parent = getParent();
                        if (parent != null) {
                            parent.requestDisallowInterceptTouchEvent(true);
                        }
                    }
                }

                if (isCanScroll) {
//                    final int activePointerIndex = event.findPointerIndex(mActivePointerId);
                    final float y = event.getY();
                    performDrag(y);
                }

                break;
            case MotionEvent.ACTION_UP:
                if (isCanScroll) {
                    Log.d(TAG, "--> state = " + state);
                    if (state == STATE_CONTENT && !isAbsolute) {
                        Log.d(TAG, "--> state == STATE_CONTENT");
                        scrollToWeb();
                    } else if (state == STATE_WEB && !isAbsolute) {
                        Log.d(TAG, "--> state == STATE == STATE_WEB");
                        scrollToContent();
                    }
                }

                break;
        }

        return true;
    }

    public boolean back() {
        boolean b = state == STATE_WEB;
        if (b) {
            scrollToContent();
        }
        return b;
    }


    public void content() {
        if (state == STATE_CONTENT) {
            scrollToWeb();
        }
    }

    private void scrollToWeb() {
        Log.d(TAG, "--> scrollToWeb");
        scroller.startScroll(getScrollX(), getScrollY(), getScrollX(), scrollHeight - getScrollY(), DURATION);
        ViewCompat.postInvalidateOnAnimation(this);
        state = STATE_WEB;
        bottom.setScroll(true);
        bottom.setEnabled(true);


        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            if (getChildAt(i) instanceof NoticeTopWebView) {
                ((NoticeTopWebView) getChildAt(i)).setScroll(false);
            }
        }
    }

    private void scrollToContent() {
        Log.d(TAG, "--> scrollToContent");
        scroller.startScroll(getScrollX(), getScrollY(), getScrollX(), -getScrollY(), DURATION);
        ViewCompat.postInvalidateOnAnimation(this);
        state = STATE_CONTENT;
        bottom.setScroll(false);
        bottom.setEnabled(false);


        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            if (getChildAt(i) instanceof NoticeTopWebView) {
                ((NoticeTopWebView) getChildAt(i)).setScroll(true);
            }
        }

    }

    private boolean performDrag(float y) {
        boolean needsInvalidate = true;

        final float deltaY = lastMotionY - y;
        lastMotionY = y;

        float oldScrollY = getScrollY();
        Log.d(TAG, "--> performDrag: oldScrollY = " + oldScrollY);

        float scrollY = oldScrollY + deltaY;


        float topBound = 0f;
        float bottomBound = scrollHeight;
        Log.d(TAG, "--> bottomBound = " + bottomBound);

        if (state == STATE_WEB) {
            topBound = 0;
        }
        if (state == STATE_CONTENT) {
            bottomBound = scrollHeight;
        }

        if (scrollY < topBound) {
            scrollY = topBound;
            isAbsolute = true;
        } else if (scrollY > bottomBound) {
            scrollY = bottomBound;
            isAbsolute = true;
        } else {
            isAbsolute = false;
        }
        // Don't lose the rounded component
        lastMotionY += scrollY - (int) scrollY;
        scrollTo(getScrollX(), ((int) scrollY));

        return false;
    }


    private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) {
        final ViewParent parent = getParent();
        if (parent != null) {
            parent.requestDisallowInterceptTouchEvent(disallowIntercept);
        }
    }

    private void resetTouch() {
//        isTopToBottom = false;
//        isBottomToTop = false;
        isCanScroll = false;
        isUnableToDrag = false;
    }

    private boolean canScroll(View v, boolean checkV, int dy, int x, int y) {
        Log.d(TAG, "--> canScroll");
        if (v instanceof ViewGroup) {
            final ViewGroup group = (ViewGroup) v;
            final int scrollX = v.getScrollX();
            final int scrollY = v.getScrollY();
            final int count = group.getChildCount();

            for (int i = count - 1; i >= 0; i--) {
                View child = group.getChildAt(i);
                if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight()
                        && y + scrollY >= child.getTop() && y + scrollY < child.getBottom()
                        && canScroll(child, true, dy, x + scrollX - child.getLeft(),
                        y + scrollY - child.getTop())) {
                    return true;
                }
            }
        }
        return checkV && ViewCompat.canScrollVertically(v, -dy);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
//        Log.d(TAG, "--> onLayout");
        int childCount = getChildCount();

        int height = 0;

        for (int i = 0; i < childCount; i++) {


            View child = getChildAt(i);
            int measuredHeight = child.getMeasuredHeight();
            Log.d(TAG, "--> onLayout:i = " + i + "measuredheight = " + measuredHeight);


            int lc = 0;
            int tc = height;
            int rc = lc + child.getMeasuredWidth();
            int bc = tc + measuredHeight;
            child.layout(lc, tc, rc, bc);
            height += measuredHeight;
            if (scrollHeight == -1 && i == 2 && measuredHeight != 0 && isLoadSuccess) {
                int i1 = screenHeight - getStatusBarHeight() - ((int) ScaleScreenHelperFactory.getInstance().getSize(100));
                scrollHeight = height < i1 ? height : i1;
//                Log.d(TAG, "--> scrollHeight = " + scrollHeight);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        Log.d(TAG, "--> onMeasure");
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);

        int height = 0;

        int count = getChildCount();
        for (int i = 2; i < count; i++) {
            View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            int childHeight = child.getMeasuredHeight();
//            Log.d(TAG, "--> i = " + i + ",childHeight = " + childHeight);


            height += childHeight;
        }

        setMeasuredDimension(sizeWidth, height);
    }

    private int getStatusBarHeight() {
        /*
         * 获取状态栏高度——方法1
         * */
        int statusBarHeight1 = -1;
//获取status_bar_height资源的ID
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根据资源ID获取响应的尺寸值
            statusBarHeight1 = getResources().getDimensionPixelSize(resourceId);
        }
        return statusBarHeight1;
    }

    @Override
    public void onScrollToBottom(boolean b) {
        isTopToBottom = b;
    }


    @Override
    public void onScrollToTop(boolean isTop) {
        isBottomToTop = isTop;
    }

    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            Log.d(TAG, "--> computeScroll:curX = " + scroller.getCurrX() + ",curY = " + scroller.getCurrY());
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            //更新界面
            postInvalidate();
        }
        super.computeScroll();
    }

    private static final Interpolator sInterpolator = new Interpolator() {
        @Override
        public float getInterpolation(float t) {
            t -= 1.0f;
            return t * t * t * t * t + 1.0f;
        }
    };

}
